﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace LowLevelGraphics.Filter
{
    public enum DISPARITY_MAP
    {
        SAD,
        ZSAD,
        LSAD,
        SSD,
        ZSSD,
        LSSD,
        NCC,
        ZNCC,
        SHD
    }

    /// <summary>
    /// Disparity has to do with steropsis, i.e. how a depth of object is percepted
    /// so this should give you 3d depth map (hope this explanation is correct) 
    /// 
    /// This is a really complex algorithm IMHO and will come later on.
    /// </summary>
    public class DisparityMap : BaseImageFilter, ITwoSourceFilter
    {
        protected DISPARITY_MAP M_MODE = DISPARITY_MAP.SAD;

        /// <summary>
        /// Initializes a new instance of the <see cref="DisparityMap"/> class.
        /// </summary>
        public DisparityMap()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="DisparityMap"/> class.
        /// </summary>
        /// <param name="_disparityMap">The _disparity map.</param>
        internal DisparityMap(DisparityMap _disparityMap)
        {
        }

        /// <summary>
        /// Gets or sets Disparity Map Mode
        /// </summary>
        public DISPARITY_MAP MODE
        {
            get { return M_MODE; }
            set { M_MODE = value; }
        }

        /// <summary>
        /// Execute this Filter
        /// A Debug Statement is written if a concrete Filter is called
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            return base.Execute(_bitmap);
        }

        /// <summary>
        /// This is used to clone a filter, each filter must implement it's own clone functionality
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new DisparityMap(this);
        }

        #region ITwoSourceFilter Members

        /// <summary>
        /// Processes the specified bmpimg.
        /// </summary>
        /// <param name="_bitmap1"></param>
        /// <param name="_bitmap2"></param>
        /// <returns></returns>
        public UnsafeBitmap Process(UnsafeBitmap _bitmap1, UnsafeBitmap _bitmap2)
        {
            int nWidth = _bitmap1.Width;
            int nHeight = _bitmap1.Height;
            UnsafeBitmap bitmap = (UnsafeBitmap)_bitmap1.Clone();
            switch (M_MODE)
            {
                case DISPARITY_MAP.SAD:
                    int nWindowSize = 16;
                    int nMeanLeft = 0;
                    int nMeanRight = 0;

                    int dMin = 0;
                    int dMax = 16;
                    for (int y = 0; y < nHeight; y++)
                    {
                        for (int x = 0; x < nWidth; x++)
                        {
                            for (int i = dMin; i < dMax; i++)
                            {
                                int nValue1 = _bitmap1.GetGrayPixelValue(x, y);
                                int nValue2 = _bitmap2.GetGrayPixelValue(x, y);
                                int nSquaredDiff = Math.Abs(nValue1 * nValue1 - nValue2 * nValue2);
                                bitmap.SetPixelDirect(x, y, Color.FromArgb(255, Color.FromArgb(nSquaredDiff)));
                            }
                        }
                    }
                    
                    OwnOptimizedConvolutionInt own = new OwnOptimizedConvolutionInt(
                        new int[,] { 
                            { 1, 1, 1 }, 
                            { 1, 1, 1 }, 
                            { 1, 1, 1 } });

                    own.Execute(bitmap);
                    GrayScale grayScale = new GrayScale();
                    grayScale.Execute(bitmap);
                    break;
            }
            return bitmap;
            //old code: return new SameColorValues(false).Process(_bitmap1, _bitmap2);
        }

        #endregion
    }
}

//int dMin = 0;
//int dMax = 16;
//List<int> aDisparity = new List<int>();
//int nValue1 = 0;
//int nValue2 = 0;
//int nSum = 0;
//for (int d = dMin; d < dMax; d++)
//{
//    nSum = 0;
//    for (int i = -nWindowSize; i < nWindowSize; i++)
//    {
//        for (int j = -nWindowSize; j < nWindowSize; j++)
//        {
//            nValue1 = _bitmap2.GetGrayPixelValue(x + i, y + j);
//            nValue2 = _bitmap2.GetGrayPixelValue(x + i + d, y + j + d);
//            nSum += Math.Abs(nValue1 - nValue2);
//        }
//    }
//    aDisparity.Add(nSum);
//}
//aDisparity.Sort();
//bitmap.SetPixel(x, y, Color.FromArgb(255, Color.FromArgb(aDisparity[1])));
